package sbc.jms.client;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Properties;

import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicSession;
import javax.jms.TopicSubscriber;
import javax.naming.Context;
import javax.naming.InitialContext;

import sbc.ejb3.Platine;
import sbc.ejb3.Sensor;
import sbc.ejb3.dao.PlatineRemote;
import sbc.ejb3.dao.SensorRemote;

/**
 * Montage
 */
public class Montage {

	public static void main(String[] args) {	
		Montage client = new Montage(args[0]);
		client.subscribe();
	}
	
	private InitialContext ctx;		
	private PlatineRemote platineRemote;
	private SensorRemote sensorRemote;
	private String mitarbeiterId;
	
	/**
	 * empty constructor
	 * initializes the client
	 *    - reads jndi.properties
	 *    - looks up PlatineRemote and SensorRemote
	 */
	public Montage(String mitarbeiterId) {
		this.mitarbeiterId = mitarbeiterId;
		
		try {
			System.out.print("Looking up Initial Context.....");
			
			Properties properties = new Properties();
			try {
		    	properties.load(new FileInputStream("resources/jndi.properties"));
			} 
			catch (IOException ioe) {
				System.out.print("error while loading properties - setting 'em manually");
				properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
				properties.put(Context.URL_PKG_PREFIXES, "org.jnp.interfaces");
				properties.put(Context.PROVIDER_URL, "localhost");
			}			
			ctx = new InitialContext(properties);
			
			platineRemote = (PlatineRemote) ctx.lookup("PlatineDAO/remote");
			sensorRemote = (SensorRemote) ctx.lookup("SensorDAO/remote");
			
			System.out.println("[OK]");
		} 
	    catch (Exception e) {
	    	System.err.println("[FAILED]\nInitial Context failure:");
	    	e.printStackTrace();
	    }	  
	}

    public void subscribe() {
    	new Subscriber().start();
    }
    
    
    /**
     * Subscriber Thread
     * connects to montageTopic and
     * waits to receive a durable message
     */
    class Subscriber extends Thread {
    	
    	public void run() {
	        System.out.println("Starting Subscriber Thread");
	        
			try {			
		        System.out.println("Looking up montageTopic");
		        Topic topic = (Topic) ctx.lookup("topic/montageTopic");
		    	
		        System.out.println("Looking up connection factory");
				TopicConnectionFactory topicConnectionFactory = (TopicConnectionFactory) ctx.lookup("TopicConnectionFactory");
				
				System.out.println("Creating connection");
				TopicConnection connection = topicConnectionFactory.createTopicConnection();
	
		        try {
		           System.out.println("Creating session");
		           TopicSession session = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
		           
		           System.out.println("Creating durable subscriber");
		           TopicSubscriber subscriber = session.createDurableSubscriber(topic, "montage");
		           
		           System.out.println("Starting connection");
		           connection.start();

		           System.out.println("entering eternity...");
		           for (;;) {
			           System.out.println("Waiting to receive message");
			           Message m = subscriber.receive();
			           
			           MapMessage message = (MapMessage)m;
			           
			           System.out.println("reading message");
			           int platineId = message.getInt("PlatineId");
			           int sensor1Id = message.getInt("Sensor1Id");
			           int sensor2Id = message.getInt("Sensor2Id");
			           
			           /*
			            * print all stored Platinen
			            */
		        	   System.out.println("platinen in db:");
			           List<Platine> platinen = platineRemote.getAll();
			           for (Platine p : platinen)	
			        	   System.out.println(p);
		        	   
		        	   /*
		        	    * do Montage
		        	    */
			           Platine platine = platineRemote.getById(platineId);
			           Sensor sensor1  = sensorRemote.getById(sensor1Id);
			           Sensor sensor2  = sensorRemote.getById(sensor2Id);
			           platine.setFirstSensor(sensor1);
			           platine.setSecondSensor(sensor2);
			           platine.setMitarbeiterId(mitarbeiterId);
		        	   platineRemote.merge(platine);			        	   

			           /*
			            * print all stored Platinen
			            */
		        	   System.out.println("platinen in db:");
			           platinen = platineRemote.getAll();
			           for (Platine p : platinen)	
			        	   System.out.println(p);			        	   
		           }
		        }
		        finally {
		        	connection.close();
			    }        
			}
			catch (Exception e) {
				System.err.println("error during message receiving: " + e);
			}
    	}
    }
}
